Computer software may be vulnerable to attacks that alter the operation of the software. For example, an exploit (so named because it exploits a vulnerability in software) such as a software worm or virus may alter existing software code, insert new code, and/or alter the order of execution of existing code from the originally intended order to induce operations that were not part of the original code as intended. Without any regulation as to acceptable entry points in software, an exploit may direct execution to any point in the software, facilitating unintended sequences of software execution because the entire software code is available for use by the exploit.
Processor architectures typically include a stack that is used for both data and control flow. The stack contains stack frames that track an activation record for every call in a call path through a program. The activation record usually contains data used by each function (local variables, parameters, etc.) along with control information (return addresses, stack pointer, etc.) that are used to reference data and/or maintain program control flow during calls and returns. Specifically, the return address is pushed onto the stack during a function call, and the called function allocates a stack frame containing its local variables on the stack including any local data buffers. Implementation bugs and unverified input may cause a program to overflow the buffers on the stack and overwrite the control data (e.g., return addresses, frame pointers). This, in turn, allows hijacking the control flow of the program by manipulating external input.
To protect against such stack-smashing attacks several mitigations have been proposed. One technique is Software Stack Protection (SSP), in which a guard value (or stack canary) is inserted on the stack next to the return address by a compiler, and the guard value is verified before the function returns. This method employs changes across the build cycle for each program that is protected in this fashion. Existing software is built with a compiler that supports Stack Canaries. To make canary values random for each run, access is provided to a random number generator. Error recovery handlers are provided to allow for recovery from stack smashing attacks. In addition to the complexity involved for each program, this technique also has size and performance overhead since each function that is protected is instrumented with code to generate canaries and perform the check. Another technique is A Stack Ghost, that instruments OS kernel trap handlers that are invoked on register window overflow situations to protect application return addresses as they are written to memory, checking for any malicious overwrites. This technique does not need application level enabling or code size costs, but relies on support register windows in the architecture. Another technique includes storing a shadow stack architecture in a separate, protected area of memory. The shadow stack is maintained either by duplicating the control information. The separate memory is allocated and managed for all threads of execution, introducing complexity.